module WhoCharted
  class ChartBase
    ACCEPTED_ARGUMENTS = [:data_range, :data, :value_method]
    ARGUMENT_DICTIONARY = {
      :data_range => {:key => 'chds', :method => :gather_data_range}
    }

    def self.accepted_arguments
      ACCEPTED_ARGUMENTS
    end

    def self.argument_dictionary
      ARGUMENT_DICTIONARY
    end

    def initialize args = {}
      @args = process_args args
    end

    def build_params
      sb = []
      self.class.argument_dictionary.each do |key, values|
        next if send(key).nil?
        sb << "&#{values[:key]}=#{(values[:method].nil? ? send(key) : send(values[:method]))}"
      end
      sb.join('')
    end

    def data_values
      @data_values ||= data[0].class == Array ? \
        data.map {|d| d.map {|o| o.send(value_method).to_f}} : \
        data.map {|d| d.send(value_method).to_f}
    end

    def gather_data_range
      data_range == :auto ? \
        auto_gather_data_range : \
        data_range.flatten.join(',')
    end

    attr_reader :args, *accepted_arguments

    private

    attr_writer *accepted_arguments

    def set_self_value key, value
      send((key.to_s + '='), value)
    end

    def process_args args
      args.each do |key, value|
        case key
        when *self.class.accepted_arguments
          set_self_value(key, value)
        end
      end
    end

    def auto_gather_data_range
      data[0].class == Array ? \
        data_values.map {|a| "#{a.min},#{a.max}"}.join(',') : \
        "#{data_values.min},#{data_values.max}"
    end
  end
end
